package cn.dark.auth.core;

import cn.hutool.core.collection.CollUtil;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * Session信息
 *
 * @author dark
 * @date 2023-10-22
 */
@Slf4j
public class AuthSession {

    /**
     * 账号id
     */
    private Object loginId;

    /**
     * 该session绑定的token
     */
    private List<TokenInfo> tokenInfos;

    /**
     * session创建时间
     */
    private Date createTime;

    /**
     * 挂载数据
     */
    private final Map<Object, Object> extraData = new ConcurrentHashMap<>();

    public AuthSession(Object loginId) {
        this.loginId = loginId;
        this.createTime = new Date();

        this.tokenInfos = Collections.synchronizedList(new ArrayList<>());
    }

    public void putData(Object key, Object value) {
        extraData.put(key, value);
    }

    public boolean putDataIfAbsent(Object key, Object value) {
        return Objects.isNull(extraData.putIfAbsent(key, value));
    }

    public Object getData(Object key) {
        return extraData.get(key);
    }

    public Object getLoginId() {
        return loginId;
    }

    public void addTokenInfo(TokenInfo tokenInfo) {
        if (tokenInfos.size() >= SysConfig.getMaxTokenSize()) {
            removeTokenInfoByCreateTime();
        }

        tokenInfos.add(tokenInfo);
    }

    public List<TokenInfo> getTokenInfos() {
        return tokenInfos;
    }

    public void removeTokenInfoByToken(String token) {
        if (StringUtils.isBlank(token)) {
            return;
        }

        getTokenInfos().removeIf(tokenInfo -> tokenInfo.getToken().equals(token));
    }

    public String removeTokenInfoByDevice(String device) {
        if (StringUtils.isBlank(device)) {
            return null;
        }

        log.info("根据设备类型【{}】移除同类型设备的token", device);

        String token = getTokenInfos().stream()
                .filter(tokenInfo -> tokenInfo.getDevice().equals(device)).map(TokenInfo::getToken).findFirst().orElse("");

        getTokenInfos().removeIf(tokenInfo -> tokenInfo.getDevice().equals(device));
        return token;
    }

    /**
     * 根据登录时间移除最早登录的用户
     */
    public void removeTokenInfoByCreateTime() {
        if (CollUtil.isEmpty(tokenInfos)) {
            return;
        }

        tokenInfos.sort(Comparator.comparing(TokenInfo::getCreateTime, Date::compareTo));
        tokenInfos.remove(0);
    }

    public List<String> getAllToken() {
        if (CollUtil.isEmpty(tokenInfos)) {
            return null;
        }

        return tokenInfos.stream().map(TokenInfo::getToken).collect(Collectors.toList());
    }

    public static class TokenInfo implements Serializable {

        private static final long serialVersionUID = 14920496536654318L;

        /**
         * token
         */
        private String token;

        /**
         * 设备类型
         */
        private String device;

        /**
         * 最后活跃时间
         */
        private Date lastActiveTime;

        /**
         * 创建时间
         */
        private Date createTime;


        public TokenInfo(String token, String device, Date lastActiveTime, Date createTime) {
            this.token = token;
            this.device = device;
            this.lastActiveTime = lastActiveTime;
            this.createTime = createTime;
        }

        public String getToken() {
            return token;
        }

        public String getDevice() {
            return device;
        }

        public Date getCreateTime() {
            return createTime;
        }

        public Date getLastActiveTime() {
            return lastActiveTime;
        }

        public void setLastActiveTime(Date lastActiveTime) {
            this.lastActiveTime = lastActiveTime;
        }
    }

}
